HW: Label the entire notebook with comments on what operation is each code chunk doing and what is the outcome

Reading the penguins dataset

library(tidyverse)
library(plotly)
Penguins<-read.csv("penguins_size.csv")

We see that the data has 344 rows and 7 columns

Penguins
dim(Penguins)
[1] 344   7

Looking at summary stats

summary(Penguins)
   species             island          culmen_length_mm culmen_depth_mm flipper_length_mm
 Length:344         Length:344         Min.   :32.10    Min.   :13.10   Min.   :172.0    
 Class :character   Class :character   1st Qu.:39.23    1st Qu.:15.60   1st Qu.:190.0    
 Mode  :character   Mode  :character   Median :44.45    Median :17.30   Median :197.0    
                                       Mean   :43.92    Mean   :17.15   Mean   :200.9    
                                       3rd Qu.:48.50    3rd Qu.:18.70   3rd Qu.:213.0    
                                       Max.   :59.60    Max.   :21.50   Max.   :231.0    
                                       NA's   :2        NA's   :2       NA's   :2        
  body_mass_g       sex           
 Min.   :2700   Length:344        
 1st Qu.:3550   Class :character  
 Median :4050   Mode  :character  
 Mean   :4202                     
 3rd Qu.:4750                     
 Max.   :6300                     
 NA's   :2                        

We notice that Species and island are read in as characters. We will convert them to factor.

Penguins$species<-as.factor(Penguins$species)
Penguins$island<-as.factor(Penguins$island)
Penguins$sex<-as.factor(Penguins$sex)

Looking at summary again

summary(Penguins)
      species          island    culmen_length_mm culmen_depth_mm flipper_length_mm
 Adelie   :152   Biscoe   :168   Min.   :32.10    Min.   :13.10   Min.   :172.0    
 Chinstrap: 68   Dream    :124   1st Qu.:39.23    1st Qu.:15.60   1st Qu.:190.0    
 Gentoo   :124   Torgersen: 52   Median :44.45    Median :17.30   Median :197.0    
                                 Mean   :43.92    Mean   :17.15   Mean   :200.9    
                                 3rd Qu.:48.50    3rd Qu.:18.70   3rd Qu.:213.0    
                                 Max.   :59.60    Max.   :21.50   Max.   :231.0    
                                 NA's   :2        NA's   :2       NA's   :2        
  body_mass_g       sex     
 Min.   :2700   .     :  1  
 1st Qu.:3550   FEMALE:165  
 Median :4050   MALE  :168  
 Mean   :4202   NA's  : 10  
 3rd Qu.:4750               
 Max.   :6300               
 NA's   :2                  

We will remove the null values and also any erroneous values for sex

Clean_DF<-na.omit(Penguins)
Clean_DF<-Clean_DF%>%
  filter(sex == 'FEMALE' | sex == 'MALE')

This leaves us with the below summary stats:

summary(Clean_DF)
      species          island    culmen_length_mm culmen_depth_mm flipper_length_mm
 Adelie   :146   Biscoe   :163   Min.   :32.10    Min.   :13.10   Min.   :172      
 Chinstrap: 68   Dream    :123   1st Qu.:39.50    1st Qu.:15.60   1st Qu.:190      
 Gentoo   :119   Torgersen: 47   Median :44.50    Median :17.30   Median :197      
                                 Mean   :43.99    Mean   :17.16   Mean   :201      
                                 3rd Qu.:48.60    3rd Qu.:18.70   3rd Qu.:213      
                                 Max.   :59.60    Max.   :21.50   Max.   :231      
  body_mass_g       sex           
 Min.   :2700   Length:333        
 1st Qu.:3550   Class :character  
 Median :4050   Mode  :character  
 Mean   :4207                     
 3rd Qu.:4775                     
 Max.   :6300                     
Clean_DF$sex<-as.factor(Clean_DF$sex)

We observe that there are 3 species 146 Adelie, 68 Chinstrap, 119 Gentoo. These penguins are spread across 3 islands named Biscoe, Dream and Torgersen The culmen length of the penguins ranged from 32.10 mm to 59.60 mm and have a average value of 43.99 mm and median value of 44.50 mm The culmen depth of the penguins ranged from 13.10 mm to 21.50 mm and have a average value of 17.16 mm and median value of 17.30 mm The flipper length of the penguins ranged from 172 mm to 231 mm and have a average value of 201 mm and median value of 197 mm The body mass of the penguins ranged from 2700 g to 6300 g and have a average value of 4207 g and median value of 4050 g Also there are 165 Female and 168 Male penguins

summary(Clean_DF)
      species          island    culmen_length_mm culmen_depth_mm flipper_length_mm
 Adelie   :146   Biscoe   :163   Min.   :32.10    Min.   :13.10   Min.   :172      
 Chinstrap: 68   Dream    :123   1st Qu.:39.50    1st Qu.:15.60   1st Qu.:190      
 Gentoo   :119   Torgersen: 47   Median :44.50    Median :17.30   Median :197      
                                 Mean   :43.99    Mean   :17.16   Mean   :201      
                                 3rd Qu.:48.60    3rd Qu.:18.70   3rd Qu.:213      
                                 Max.   :59.60    Max.   :21.50   Max.   :231      
  body_mass_g       sex     
 Min.   :2700   FEMALE:165  
 1st Qu.:3550   MALE  :168  
 Median :4050               
 Mean   :4207               
 3rd Qu.:4775               
 Max.   :6300               

We now graphically represent the same summary statistics in a boxplot to also check if there are ouliers. There are no outliers in culmen length, culmen depth or flipper length

boxplot(Clean_DF[3:5])

There are no outliers in body mass either

boxplot(Clean_DF$body_mass_g)

We now look at the distribution of the body mass based on sex. There are no outliers however the distributions are different for each sex Minimum weight for female is below 3000 g while that for males is above 3000 g. Maximum weight for females is slightly above 5000 while it is above 6000 for males The median value for female is between 3000 and 4000 while that of male is between 4000 and 5000

p<-ggplot(Clean_DF, aes(sex, body_mass_g, fill=sex))+
  geom_boxplot()

ggplotly(p)

We now look at the distribution of the culmen length based on sex. There are no outliers however the distributions are different for each sex Minimum value for female is slightly below the minimum value for males, both lie between 30 and 40. Maximum for females and males are close to 60 but the max for females is slightly lower Median for females and males are close to 45 but the median for females is slightly lower

p<-ggplot(Clean_DF, aes(sex, culmen_length_mm, fill=sex))+
  geom_boxplot()

ggplotly(p)

We now look at the distribution of the culmen depth based on sex. There are no outliers however the distributions are different for each sex Minimum value for female is slightly below the minimum value for males, both lie between 12.5 and 15. Maximum for females and males are greater than 20 but the max for females is slightly lower Median for females is below 17.5 and that of males is above 17.5

p<-ggplot(Clean_DF, aes(sex, culmen_depth_mm, fill=sex))+
  geom_boxplot()

ggplotly(p)

We now look at the distribution of the flipper length based on sex. There are no outliers however the distributions are different for each sex Minimum value for female is slightly below the minimum value for males, both lie between 170 and 180. Maximum for females and males are greater than 220 and 230 respectively. Median for females is above 190 and that of males is above 200

p<-ggplot(Clean_DF, aes(sex, flipper_length_mm, fill=sex))+
  geom_boxplot()

ggplotly(p)

Looking at body measures by Species

p<-ggplot(Clean_DF, aes(species, body_mass_g, fill=species))+
  geom_boxplot()

ggplotly(p)
p<-ggplot(Clean_DF, aes(species, culmen_length_mm, fill=species))+
  geom_boxplot()

ggplotly(p)
p<-ggplot(Clean_DF, aes(species, culmen_depth_mm, fill=species))+
  geom_boxplot()

ggplotly(p)
p<-ggplot(Clean_DF, aes(species, flipper_length_mm, fill=species))+
  geom_boxplot()

ggplotly(p)
p<-ggplot(data = Clean_DF) + 
  geom_bar(mapping = aes(x = species, fill=species))

ggplotly(p)

We see here that the Adelie species is spread across all islands where as Chinstrap is exclusive to Dream island while Gentoo is exclusive to Biscoe

p<-ggplot(data = Clean_DF) + 
  geom_bar(mapping = aes(x = island, fill=species))

ggplotly(p)

We observe from the scatterplot that the different species are almost separable based on the length and depth of the culmen. The red points represent Adelie, green point chinstrap and blue Gentoo. Also there is a positive correlation between the two variables

p<-ggplot(data = Clean_DF) + 
  geom_point(mapping = aes(x = culmen_length_mm, y = culmen_depth_mm,color = species, shape=island))

ggplotly(p)

We observe from the scatterplot that the different species are almost separable based on the length of the culmen and flipper. The red points represent Adelie, green point chinstrap and blue Gentoo.

The flipper length is also highly correlated with the culmen length

p<-ggplot(data = Clean_DF) + 
  geom_point(mapping = aes(x = culmen_length_mm, y = flipper_length_mm,color = species, shape=island))

ggplotly(p)
p<-ggplot(data = Clean_DF) + 
  geom_point(mapping = aes(x = culmen_length_mm, y = body_mass_g, color = species, shape=island))

ggplotly(p)

We can observe the actual magnitude of correlation from the plot below. Culmen length and and culmen depth aren’t highly correlated, but as seen above they are highly correlated among each species.

Culmen length is highly correlated with flipper length and body mass and both are positively correlated

Culmen depth is highly correlated with flipper length but is a negative correlation

Flipper length and body mass show high positive correlated

library(corrplot)
M<-cor(Clean_DF[3:6])
corrplot(M,method="color",addCoef.col = "white")

LS0tCnRpdGxlOiAiUGVuZ3VpbiBEYXRhIEVEQSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKSFc6IExhYmVsIHRoZSBlbnRpcmUgbm90ZWJvb2sgd2l0aCBjb21tZW50cyBvbiB3aGF0IG9wZXJhdGlvbiBpcyBlYWNoIGNvZGUgY2h1bmsgZG9pbmcgYW5kIHdoYXQgaXMgdGhlIG91dGNvbWUKClJlYWRpbmcgdGhlIHBlbmd1aW5zIGRhdGFzZXQKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBsb3RseSkKUGVuZ3VpbnM8LXJlYWQuY3N2KCJwZW5ndWluc19zaXplLmNzdiIpCmBgYAoKV2Ugc2VlIHRoYXQgdGhlIGRhdGEgaGFzIDM0NCByb3dzIGFuZCA3IGNvbHVtbnMKCmBgYHtyfQpQZW5ndWlucwpkaW0oUGVuZ3VpbnMpCmBgYAoKTG9va2luZyBhdCBzdW1tYXJ5IHN0YXRzCmBgYHtyfQpzdW1tYXJ5KFBlbmd1aW5zKQpgYGAKV2Ugbm90aWNlIHRoYXQgU3BlY2llcyBhbmQgaXNsYW5kIGFyZSByZWFkIGluIGFzIGNoYXJhY3RlcnMuIFdlIHdpbGwgY29udmVydCB0aGVtIHRvIGZhY3Rvci4KYGBge3J9ClBlbmd1aW5zJHNwZWNpZXM8LWFzLmZhY3RvcihQZW5ndWlucyRzcGVjaWVzKQpQZW5ndWlucyRpc2xhbmQ8LWFzLmZhY3RvcihQZW5ndWlucyRpc2xhbmQpClBlbmd1aW5zJHNleDwtYXMuZmFjdG9yKFBlbmd1aW5zJHNleCkKYGBgCgpMb29raW5nIGF0IHN1bW1hcnkgYWdhaW4KYGBge3J9CnN1bW1hcnkoUGVuZ3VpbnMpCmBgYApXZSB3aWxsIHJlbW92ZSB0aGUgbnVsbCB2YWx1ZXMgYW5kIGFsc28gYW55IGVycm9uZW91cyB2YWx1ZXMgZm9yIHNleCAgCmBgYHtyfQpDbGVhbl9ERjwtbmEub21pdChQZW5ndWlucykKQ2xlYW5fREY8LUNsZWFuX0RGJT4lCiAgZmlsdGVyKHNleCA9PSAnRkVNQUxFJyB8IHNleCA9PSAnTUFMRScpCmBgYAoKVGhpcyBsZWF2ZXMgdXMgd2l0aCB0aGUgYmVsb3cgc3VtbWFyeSBzdGF0czoKCgpgYGB7cn0Kc3VtbWFyeShDbGVhbl9ERikKYGBgCgpgYGB7cn0KQ2xlYW5fREYkc2V4PC1hcy5mYWN0b3IoQ2xlYW5fREYkc2V4KQpgYGAKV2Ugb2JzZXJ2ZSB0aGF0IHRoZXJlIGFyZSAzIHNwZWNpZXMgMTQ2IEFkZWxpZSwgNjggQ2hpbnN0cmFwLCAxMTkgR2VudG9vLiAKVGhlc2UgcGVuZ3VpbnMgYXJlIHNwcmVhZCBhY3Jvc3MgMyBpc2xhbmRzIG5hbWVkIEJpc2NvZSwgRHJlYW0gYW5kIFRvcmdlcnNlbgpUaGUgY3VsbWVuIGxlbmd0aCBvZiB0aGUgcGVuZ3VpbnMgcmFuZ2VkIGZyb20gMzIuMTAgbW0gdG8gNTkuNjAgbW0gYW5kIGhhdmUgYSBhdmVyYWdlIHZhbHVlIG9mIDQzLjk5IG1tIGFuZCBtZWRpYW4gdmFsdWUgb2YgNDQuNTAgbW0KVGhlIGN1bG1lbiBkZXB0aCBvZiB0aGUgcGVuZ3VpbnMgcmFuZ2VkIGZyb20gMTMuMTAgbW0gdG8gMjEuNTAgbW0gYW5kIGhhdmUgYSBhdmVyYWdlIHZhbHVlIG9mIDE3LjE2IG1tIGFuZCBtZWRpYW4gdmFsdWUgb2YgMTcuMzAgbW0KVGhlIGZsaXBwZXIgbGVuZ3RoIG9mIHRoZSBwZW5ndWlucyByYW5nZWQgZnJvbSAxNzIgbW0gdG8gMjMxIG1tIGFuZCBoYXZlIGEgYXZlcmFnZSB2YWx1ZSBvZiAyMDEgbW0gYW5kIG1lZGlhbiB2YWx1ZSBvZiAxOTcgbW0KVGhlIGJvZHkgbWFzcyBvZiB0aGUgcGVuZ3VpbnMgcmFuZ2VkIGZyb20gMjcwMCBnIHRvIDYzMDAgZyBhbmQgaGF2ZSBhIGF2ZXJhZ2UgdmFsdWUgb2YgNDIwNyBnIGFuZCBtZWRpYW4gdmFsdWUgb2YgNDA1MCBnCkFsc28gdGhlcmUgYXJlIDE2NSBGZW1hbGUgYW5kIDE2OCBNYWxlIHBlbmd1aW5zCmBgYHtyfQpzdW1tYXJ5KENsZWFuX0RGKQpgYGAKV2Ugbm93IGdyYXBoaWNhbGx5IHJlcHJlc2VudCB0aGUgc2FtZSBzdW1tYXJ5IHN0YXRpc3RpY3MgaW4gYSBib3hwbG90IHRvIGFsc28gY2hlY2sgaWYgdGhlcmUgYXJlIG91bGllcnMuClRoZXJlIGFyZSBubyBvdXRsaWVycyBpbiBjdWxtZW4gbGVuZ3RoLCBjdWxtZW4gZGVwdGggb3IgZmxpcHBlciBsZW5ndGgKYGBge3J9CmJveHBsb3QoQ2xlYW5fREZbMzo1XSkKYGBgClRoZXJlIGFyZSBubyBvdXRsaWVycyBpbiBib2R5IG1hc3MgZWl0aGVyCmBgYHtyfQpib3hwbG90KENsZWFuX0RGJGJvZHlfbWFzc19nKQpgYGAKV2Ugbm93IGxvb2sgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgYm9keSBtYXNzIGJhc2VkIG9uIHNleC4gVGhlcmUgYXJlIG5vIG91dGxpZXJzIGhvd2V2ZXIgdGhlIGRpc3RyaWJ1dGlvbnMgYXJlIGRpZmZlcmVudCBmb3IgZWFjaCBzZXgKTWluaW11bSB3ZWlnaHQgZm9yIGZlbWFsZSBpcyBiZWxvdyAzMDAwIGcgd2hpbGUgdGhhdCBmb3IgbWFsZXMgaXMgYWJvdmUgMzAwMCBnLiBNYXhpbXVtIHdlaWdodCBmb3IgZmVtYWxlcyBpcyBzbGlnaHRseSBhYm92ZSA1MDAwIHdoaWxlIGl0IGlzIGFib3ZlIDYwMDAgZm9yIG1hbGVzClRoZSBtZWRpYW4gdmFsdWUgZm9yIGZlbWFsZSBpcyBiZXR3ZWVuIDMwMDAgYW5kIDQwMDAgd2hpbGUgdGhhdCBvZiBtYWxlIGlzIGJldHdlZW4gNDAwMCBhbmQgNTAwMApgYGB7cn0KcDwtZ2dwbG90KENsZWFuX0RGLCBhZXMoc2V4LCBib2R5X21hc3NfZywgZmlsbD1zZXgpKSsKICBnZW9tX2JveHBsb3QoKQoKZ2dwbG90bHkocCkKYGBgCgpXZSBub3cgbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjdWxtZW4gbGVuZ3RoIGJhc2VkIG9uIHNleC4gVGhlcmUgYXJlIG5vIG91dGxpZXJzIGhvd2V2ZXIgdGhlIGRpc3RyaWJ1dGlvbnMgYXJlIGRpZmZlcmVudCBmb3IgZWFjaCBzZXgKTWluaW11bSB2YWx1ZSBmb3IgZmVtYWxlIGlzIHNsaWdodGx5IGJlbG93IHRoZSBtaW5pbXVtIHZhbHVlIGZvciBtYWxlcywgYm90aCBsaWUgYmV0d2VlbiAzMCBhbmQgNDAuIE1heGltdW0gZm9yIGZlbWFsZXMgYW5kICBtYWxlcyBhcmUgY2xvc2UgdG8gNjAgYnV0IHRoZSBtYXggZm9yIGZlbWFsZXMgaXMgc2xpZ2h0bHkgbG93ZXIKTWVkaWFuIGZvciBmZW1hbGVzIGFuZCAgbWFsZXMgYXJlIGNsb3NlIHRvIDQ1IGJ1dCB0aGUgbWVkaWFuIGZvciBmZW1hbGVzIGlzIHNsaWdodGx5IGxvd2VyCgpgYGB7cn0KcDwtZ2dwbG90KENsZWFuX0RGLCBhZXMoc2V4LCBjdWxtZW5fbGVuZ3RoX21tLCBmaWxsPXNleCkpKwogIGdlb21fYm94cGxvdCgpCgpnZ3Bsb3RseShwKQpgYGAKCldlIG5vdyBsb29rIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGN1bG1lbiBkZXB0aCBiYXNlZCBvbiBzZXguIFRoZXJlIGFyZSBubyBvdXRsaWVycyBob3dldmVyIHRoZSBkaXN0cmlidXRpb25zIGFyZSBkaWZmZXJlbnQgZm9yIGVhY2ggc2V4Ck1pbmltdW0gdmFsdWUgZm9yIGZlbWFsZSBpcyBzbGlnaHRseSBiZWxvdyB0aGUgbWluaW11bSB2YWx1ZSBmb3IgbWFsZXMsIGJvdGggbGllIGJldHdlZW4gMTIuNSBhbmQgMTUuIE1heGltdW0gZm9yIGZlbWFsZXMgYW5kICBtYWxlcyBhcmUgZ3JlYXRlciB0aGFuIDIwIGJ1dCB0aGUgbWF4IGZvciBmZW1hbGVzIGlzIHNsaWdodGx5IGxvd2VyCk1lZGlhbiBmb3IgZmVtYWxlcyBpcyBiZWxvdyAxNy41IGFuZCAgdGhhdCBvZiBtYWxlcyBpcyBhYm92ZSAxNy41CmBgYHtyfQpwPC1nZ3Bsb3QoQ2xlYW5fREYsIGFlcyhzZXgsIGN1bG1lbl9kZXB0aF9tbSwgZmlsbD1zZXgpKSsKICBnZW9tX2JveHBsb3QoKQoKZ2dwbG90bHkocCkKYGBgCldlIG5vdyBsb29rIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGZsaXBwZXIgbGVuZ3RoIGJhc2VkIG9uIHNleC4gVGhlcmUgYXJlIG5vIG91dGxpZXJzIGhvd2V2ZXIgdGhlIGRpc3RyaWJ1dGlvbnMgYXJlIGRpZmZlcmVudCBmb3IgZWFjaCBzZXgKTWluaW11bSB2YWx1ZSBmb3IgZmVtYWxlIGlzIHNsaWdodGx5IGJlbG93IHRoZSBtaW5pbXVtIHZhbHVlIGZvciBtYWxlcywgYm90aCBsaWUgYmV0d2VlbiAxNzAgYW5kIDE4MC4gTWF4aW11bSBmb3IgZmVtYWxlcyBhbmQgIG1hbGVzIGFyZSBncmVhdGVyIHRoYW4gMjIwIGFuZCAyMzAgcmVzcGVjdGl2ZWx5LiBNZWRpYW4gZm9yIGZlbWFsZXMgaXMgYWJvdmUgMTkwIGFuZCAgdGhhdCBvZiBtYWxlcyBpcyBhYm92ZSAyMDAKYGBge3J9CnA8LWdncGxvdChDbGVhbl9ERiwgYWVzKHNleCwgZmxpcHBlcl9sZW5ndGhfbW0sIGZpbGw9c2V4KSkrCiAgZ2VvbV9ib3hwbG90KCkKCmdncGxvdGx5KHApCmBgYAoKTG9va2luZyBhdCBib2R5IG1lYXN1cmVzIGJ5IFNwZWNpZXMKCmBgYHtyfQpwPC1nZ3Bsb3QoQ2xlYW5fREYsIGFlcyhzcGVjaWVzLCBib2R5X21hc3NfZywgZmlsbD1zcGVjaWVzKSkrCiAgZ2VvbV9ib3hwbG90KCkKCmdncGxvdGx5KHApCmBgYAoKYGBge3J9CnA8LWdncGxvdChDbGVhbl9ERiwgYWVzKHNwZWNpZXMsIGN1bG1lbl9sZW5ndGhfbW0sIGZpbGw9c3BlY2llcykpKwogIGdlb21fYm94cGxvdCgpCgpnZ3Bsb3RseShwKQpgYGAKCgpgYGB7cn0KcDwtZ2dwbG90KENsZWFuX0RGLCBhZXMoc3BlY2llcywgY3VsbWVuX2RlcHRoX21tLCBmaWxsPXNwZWNpZXMpKSsKICBnZW9tX2JveHBsb3QoKQoKZ2dwbG90bHkocCkKYGBgCgpgYGB7cn0KcDwtZ2dwbG90KENsZWFuX0RGLCBhZXMoc3BlY2llcywgZmxpcHBlcl9sZW5ndGhfbW0sIGZpbGw9c3BlY2llcykpKwogIGdlb21fYm94cGxvdCgpCgpnZ3Bsb3RseShwKQpgYGAKCmBgYHtyfQpwPC1nZ3Bsb3QoZGF0YSA9IENsZWFuX0RGKSArIAogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IHNwZWNpZXMsIGZpbGw9c3BlY2llcykpCgpnZ3Bsb3RseShwKQpgYGAKV2Ugc2VlIGhlcmUgdGhhdCB0aGUgQWRlbGllIHNwZWNpZXMgaXMgc3ByZWFkIGFjcm9zcyBhbGwgaXNsYW5kcyB3aGVyZSBhcyBDaGluc3RyYXAgaXMgZXhjbHVzaXZlIHRvIERyZWFtIGlzbGFuZCB3aGlsZSBHZW50b28gaXMgZXhjbHVzaXZlIHRvIEJpc2NvZQpgYGB7cn0KcDwtZ2dwbG90KGRhdGEgPSBDbGVhbl9ERikgKyAKICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBpc2xhbmQsIGZpbGw9c3BlY2llcykpCgpnZ3Bsb3RseShwKQpgYGAKCldlIG9ic2VydmUgZnJvbSB0aGUgc2NhdHRlcnBsb3QgdGhhdCB0aGUgZGlmZmVyZW50IHNwZWNpZXMgYXJlIGFsbW9zdCBzZXBhcmFibGUgYmFzZWQgb24gdGhlIGxlbmd0aCBhbmQgZGVwdGggb2YgdGhlIGN1bG1lbi4gVGhlIHJlZCBwb2ludHMgcmVwcmVzZW50IEFkZWxpZSwgZ3JlZW4gcG9pbnQgY2hpbnN0cmFwIGFuZCBibHVlIEdlbnRvby4gQWxzbyB0aGVyZSBpcyBhIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMKCmBgYHtyfQpwPC1nZ3Bsb3QoZGF0YSA9IENsZWFuX0RGKSArIAogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gY3VsbWVuX2xlbmd0aF9tbSwgeSA9IGN1bG1lbl9kZXB0aF9tbSxjb2xvciA9IHNwZWNpZXMsIHNoYXBlPWlzbGFuZCkpCgpnZ3Bsb3RseShwKQpgYGAKCldlIG9ic2VydmUgZnJvbSB0aGUgc2NhdHRlcnBsb3QgdGhhdCB0aGUgZGlmZmVyZW50IHNwZWNpZXMgYXJlIGFsbW9zdCBzZXBhcmFibGUgYmFzZWQgb24gdGhlIGxlbmd0aCBvZiB0aGUgY3VsbWVuIGFuZCBmbGlwcGVyLiBUaGUgcmVkIHBvaW50cyByZXByZXNlbnQgQWRlbGllLCBncmVlbiBwb2ludCBjaGluc3RyYXAgYW5kIGJsdWUgR2VudG9vLgoKVGhlIGZsaXBwZXIgbGVuZ3RoIGlzIGFsc28gaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCB0aGUgY3VsbWVuIGxlbmd0aAoKYGBge3J9CnA8LWdncGxvdChkYXRhID0gQ2xlYW5fREYpICsgCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBjdWxtZW5fbGVuZ3RoX21tLCB5ID0gZmxpcHBlcl9sZW5ndGhfbW0sY29sb3IgPSBzcGVjaWVzLCBzaGFwZT1pc2xhbmQpKQoKZ2dwbG90bHkocCkKYGBgCgpgYGB7cn0KcDwtZ2dwbG90KGRhdGEgPSBDbGVhbl9ERikgKyAKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGN1bG1lbl9sZW5ndGhfbW0sIHkgPSBib2R5X21hc3NfZywgY29sb3IgPSBzcGVjaWVzLCBzaGFwZT1pc2xhbmQpKQoKZ2dwbG90bHkocCkKYGBgCgpXZSBjYW4gb2JzZXJ2ZSB0aGUgYWN0dWFsIG1hZ25pdHVkZSBvZiBjb3JyZWxhdGlvbiBmcm9tIHRoZSBwbG90IGJlbG93LiBDdWxtZW4gbGVuZ3RoIGFuZCBhbmQgY3VsbWVuIGRlcHRoIGFyZW4ndCBoaWdobHkgY29ycmVsYXRlZCwgYnV0IGFzIHNlZW4gYWJvdmUgdGhleSBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgYW1vbmcgZWFjaCBzcGVjaWVzLiAKCkN1bG1lbiBsZW5ndGggaXMgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBmbGlwcGVyIGxlbmd0aCBhbmQgYm9keSBtYXNzIGFuZCBib3RoIGFyZSBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQKCkN1bG1lbiBkZXB0aCBpcyBoaWdobHkgY29ycmVsYXRlZCB3aXRoIGZsaXBwZXIgbGVuZ3RoIGJ1dCBpcyBhIG5lZ2F0aXZlIGNvcnJlbGF0aW9uCgpGbGlwcGVyIGxlbmd0aCBhbmQgYm9keSBtYXNzIHNob3cgaGlnaCBwb3NpdGl2ZSBjb3JyZWxhdGVkCmBgYHtyfQpsaWJyYXJ5KGNvcnJwbG90KQpNPC1jb3IoQ2xlYW5fREZbMzo2XSkKY29ycnBsb3QoTSxtZXRob2Q9ImNvbG9yIixhZGRDb2VmLmNvbCA9ICJ3aGl0ZSIpCmBgYAoK